﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using System.Threading;
using MMessaging.MessagingEx.Common;

namespace MMessaging.MessagingEx.Queues
{
	/// <summary>
	/// Repräsentiert eine Messagequeue für den einfachen Nachrichtentransport innerhalb eines 
	/// Betriebssystem-Prozesses. Simplex-Verfahren == Unidirektional.
	/// </summary>
	/// <typeparam name="MESSAGETYPE"></typeparam>
	public class MChannelInterThread<MESSAGETYPE> :
		IMChannel<MESSAGETYPE> 
		where MESSAGETYPE : class
	{
		#region private

		private ConcurrentQueue<MESSAGETYPE> _messageQueue = new ConcurrentQueue<MESSAGETYPE>();

		private ManualResetEvent _signal = new ManualResetEvent(false);

		#endregion

		#region public 

		/// <summary>
		/// constructor
		/// </summary>
		/// <param name="name">
		/// logging name of this channel
		/// </param>
		public MChannelInterThread(string name)
		{
			Name = name;
		}

		/// <summary>
		/// Blockiert bis eine Message bereit steht oder der übergebene Timeout ausläuft.
		/// </summary>
		/// <param name="timeout"></param>
		/// <returns>
		/// null, wenn der Timeout ausgelaufen ist.
		/// </returns>
		public MESSAGETYPE WaitForMessage(int timeout)
		{
			MESSAGETYPE message;

			_signal.Reset();

			if (_messageQueue.TryDequeue(out message))
			{
				// System.Diagnostics.Debug.WriteLine("GTZZGX channel: " + Name + "; WaitForMessage() returns " + message ?? "null");
				return message;
			}

			_signal.WaitOne(timeout);

			if (_messageQueue.TryDequeue(out message))
			{
				// System.Diagnostics.Debug.WriteLine("GTZZGX channel: " + Name + "; WaitForMessage() returns " + message ?? "null");
				return message;
			}

			// System.Diagnostics.Debug.WriteLine("GTZZGX channel: " + Name + "; WaitForMessage() returns null");
			return null;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="message"></param>
		public void PostMessage(MESSAGETYPE message)
		{
			// System.Diagnostics.Debug.WriteLine("GTZZGX channel: " + Name + "; PostMessage() entered " + message ?? "null");
			_messageQueue.Enqueue(message);
			_signal.Set();
		}

		public WaitHandle[] WaitSignals
		{
			get 
			{
				return new WaitHandle[] { _signal };
			}
		}

		public string Name { get; private set; }

		#endregion


	}
}
